/**
 * 时间格式化工具类
 * 提供各种时间格式化功能
 */

/**
 * 格式化日期时间
 * @param {Date|string|number} date - 日期对象、日期字符串或时间戳
 * @param {string} format - 格式化模板，支持以下占位符：
 *   - YYYY: 四位年份
 *   - YY: 两位年份
 *   - MM: 两位月份
 *   - M: 月份
 *   - DD: 两位日期
 *   - D: 日期
 *   - HH: 两位小时(24小时制)
 *   - H: 小时(24小时制)
 *   - hh: 两位小时(12小时制)
 *   - h: 小时(12小时制)
 *   - mm: 两位分钟
 *   - m: 分钟
 *   - ss: 两位秒数
 *   - s: 秒数
 *   - SSS: 毫秒
 *   - A: 上午/下午
 * @returns {string} 格式化后的时间字符串
 * @example
 * formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss') // '2024-01-15 14:30:25'
 * formatDate('2024-01-15', 'MM/DD/YYYY') // '01/15/2024'
 * formatDate(1705308625000, 'YYYY年MM月DD日') // '2024年01月15日'
 */
export const formatDate = (date, format = 'YYYY-MM-DD HH:mm:ss') => {
  if (!date) return ''

  const d = new Date(date)
  if (isNaN(d.getTime())) return ''

  const year = d.getFullYear()
  const month = d.getMonth() + 1
  const day = d.getDate()
  const hour = d.getHours()
  const minute = d.getMinutes()
  const second = d.getSeconds()
  const millisecond = d.getMilliseconds()

  // 12小时制转换
  const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour
  const ampm = hour < 12 ? '上午' : '下午'

  const formatMap = {
    'YYYY': year.toString(),
    'YY': year.toString().slice(-2),
    'MM': month.toString().padStart(2, '0'),
    'M': month.toString(),
    'DD': day.toString().padStart(2, '0'),
    'D': day.toString(),
    'HH': hour.toString().padStart(2, '0'),
    'H': hour.toString(),
    'hh': hour12.toString().padStart(2, '0'),
    'h': hour12.toString(),
    'mm': minute.toString().padStart(2, '0'),
    'm': minute.toString(),
    'ss': second.toString().padStart(2, '0'),
    's': second.toString(),
    'SSS': millisecond.toString().padStart(3, '0'),
    'A': ampm
  }

  let result = format
  Object.keys(formatMap).forEach(key => {
    result = result.replace(new RegExp(key, 'g'), formatMap[key])
  })

  return result
}

/**
 * 获取相对时间描述
 * @param {Date|string|number} date - 日期对象、日期字符串或时间戳
 * @param {Date|string|number} baseDate - 基准时间，默认为当前时间
 * @returns {string} 相对时间描述
 * @example
 * getRelativeTime(new Date(Date.now() - 60000)) // '1分钟前'
 * getRelativeTime(new Date(Date.now() - 3600000)) // '1小时前'
 * getRelativeTime(new Date(Date.now() + 86400000)) // '1天后'
 */
export const getRelativeTime = (date, baseDate = new Date()) => {
  if (!date) return ''

  const targetDate = new Date(date)
  const base = new Date(baseDate)

  if (isNaN(targetDate.getTime()) || isNaN(base.getTime())) return ''

  const diff = base.getTime() - targetDate.getTime()
  const absDiff = Math.abs(diff)
  const isFuture = diff < 0

  const minute = 60 * 1000
  const hour = 60 * minute
  const day = 24 * hour
  const week = 7 * day
  const month = 30 * day
  const year = 365 * day

  let result = ''

  if (absDiff < minute) {
    result = '刚刚'
  } else if (absDiff < hour) {
    const minutes = Math.floor(absDiff / minute)
    result = `${minutes}分钟${isFuture ? '后' : '前'}`
  } else if (absDiff < day) {
    const hours = Math.floor(absDiff / hour)
    result = `${hours}小时${isFuture ? '后' : '前'}`
  } else if (absDiff < week) {
    const days = Math.floor(absDiff / day)
    result = `${days}天${isFuture ? '后' : '前'}`
  } else if (absDiff < month) {
    const weeks = Math.floor(absDiff / week)
    result = `${weeks}周${isFuture ? '后' : '前'}`
  } else if (absDiff < year) {
    const months = Math.floor(absDiff / month)
    result = `${months}个月${isFuture ? '后' : '前'}`
  } else {
    const years = Math.floor(absDiff / year)
    result = `${years}年${isFuture ? '后' : '前'}`
  }

  return result
}

/**
 * 格式化时间戳
 * @param {number} timestamp - 时间戳（毫秒）
 * @param {string} format - 格式化模板
 * @returns {string} 格式化后的时间字符串
 * @example
 * formatTimestamp(1705308625000) // '2024-01-15 14:30:25'
 * formatTimestamp(1705308625000, 'MM-DD HH:mm') // '01-15 14:30'
 */
export const formatTimestamp = (timestamp, format = 'YYYY-MM-DD HH:mm:ss') => {
  return formatDate(new Date(timestamp), format)
}

/**
 * 获取星期几
 * @param {Date|string|number} date - 日期对象、日期字符串或时间戳
 * @param {string} type - 返回类型：'zh'(中文) | 'en'(英文) | 'short'(简写)
 * @returns {string} 星期几
 * @example
 * getWeekday(new Date(), 'zh') // '星期一'
 * getWeekday(new Date(), 'en') // 'Monday'
 * getWeekday(new Date(), 'short') // '周一'
 */
export const getWeekday = (date, type = 'zh') => {
  if (!date) return ''

  const d = new Date(date)
  if (isNaN(d.getTime())) return ''

  const weekday = d.getDay()

  const weekdays = {
    zh: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
    en: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
    short: ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
  }

  return weekdays[type] ? weekdays[type][weekday] : weekdays.zh[weekday]
}

/**
 * 格式化日期范围
 * @param {Date|string|number} startDate - 开始日期
 * @param {Date|string|number} endDate - 结束日期
 * @param {string} format - 格式化模板
 * @param {string} separator - 分隔符，默认为 ' ~ '
 * @returns {string} 格式化后的日期范围字符串
 * @example
 * formatDateRange('2024-01-15', '2024-01-20') // '2024-01-15 ~ 2024-01-20'
 * formatDateRange('2024-01-15', '2024-01-20', 'MM/DD', ' 至 ') // '01/15 至 01/20'
 */
export const formatDateRange = (startDate, endDate, format = 'YYYY-MM-DD', separator = ' ~ ') => {
  if (!startDate || !endDate) return ''

  const start = formatDate(startDate, format)
  const end = formatDate(endDate, format)

  if (!start || !end) return ''

  return `${start}${separator}${end}`
}

/**
 * 获取时间段描述
 * @param {Date|string|number} date - 日期对象、日期字符串或时间戳
 * @returns {string} 时间段描述
 * @example
 * getTimePeriod(new Date('2024-01-15 08:30:00')) // '上午'
 * getTimePeriod(new Date('2024-01-15 14:30:00')) // '下午'
 * getTimePeriod(new Date('2024-01-15 20:30:00')) // '晚上'
 */
export const getTimePeriod = (date) => {
  if (!date) return ''

  const d = new Date(date)
  if (isNaN(d.getTime())) return ''

  const hour = d.getHours()

  if (hour >= 6 && hour < 12) {
    return '上午'
  } else if (hour >= 12 && hour < 18) {
    return '下午'
  } else if (hour >= 18 && hour < 24) {
    return '晚上'
  } else {
    return '凌晨'
  }
}

/**
 * 计算两个日期之间的天数差
 * @param {Date|string|number} startDate - 开始日期
 * @param {Date|string|number} endDate - 结束日期
 * @returns {number} 天数差（正数表示endDate在startDate之后）
 * @example
 * getDaysDiff('2024-01-15', '2024-01-20') // 5
 * getDaysDiff('2024-01-20', '2024-01-15') // -5
 */
export const getDaysDiff = (startDate, endDate) => {
  if (!startDate || !endDate) return 0

  const start = new Date(startDate)
  const end = new Date(endDate)

  if (isNaN(start.getTime()) || isNaN(end.getTime())) return 0

  const diffTime = end.getTime() - start.getTime()
  return Math.ceil(diffTime / (1000 * 60 * 60 * 24))
}

/**
 * 判断是否为今天
 * @param {Date|string|number} date - 日期对象、日期字符串或时间戳
 * @returns {boolean} 是否为今天
 * @example
 * isToday(new Date()) // true
 * isToday('2024-01-15') // 根据当前日期判断
 */
export const isToday = (date) => {
  if (!date) return false

  const d = new Date(date)
  const today = new Date()

  if (isNaN(d.getTime())) return false

  return d.toDateString() === today.toDateString()
}

/**
 * 判断是否为昨天
 * @param {Date|string|number} date - 日期对象、日期字符串或时间戳
 * @returns {boolean} 是否为昨天
 * @example
 * isYesterday(new Date(Date.now() - 86400000)) // true
 */
export const isYesterday = (date) => {
  if (!date) return false

  const d = new Date(date)
  const yesterday = new Date()
  yesterday.setDate(yesterday.getDate() - 1)

  if (isNaN(d.getTime())) return false

  return d.toDateString() === yesterday.toDateString()
}

/**
 * 判断是否为明天
 * @param {Date|string|number} date - 日期对象、日期字符串或时间戳
 * @returns {boolean} 是否为明天
 * @example
 * isTomorrow(new Date(Date.now() + 86400000)) // true
 */
export const isTomorrow = (date) => {
  if (!date) return false

  const d = new Date(date)
  const tomorrow = new Date()
  tomorrow.setDate(tomorrow.getDate() + 1)

  if (isNaN(d.getTime())) return false

  return d.toDateString() === tomorrow.toDateString()
}

/**
 * 获取友好的日期显示
 * @param {Date|string|number} date - 日期对象、日期字符串或时间戳
 * @param {boolean} showTime - 是否显示时间，默认为false
 * @returns {string} 友好的日期显示
 * @example
 * getFriendlyDate(new Date()) // '今天'
 * getFriendlyDate(new Date(), true) // '今天 14:30'
 * getFriendlyDate(new Date(Date.now() - 86400000)) // '昨天'
 */
export const getFriendlyDate = (date, showTime = false) => {
  if (!date) return ''

  const d = new Date(date)
  if (isNaN(d.getTime())) return ''

  let result = ''

  if (isToday(date)) {
    result = '今天'
  } else if (isYesterday(date)) {
    result = '昨天'
  } else if (isTomorrow(date)) {
    result = '明天'
  } else {
    result = formatDate(date, 'MM-DD')
  }

  if (showTime) {
    result += ' ' + formatDate(date, 'HH:mm')
  }

  return result
}

/**
 * 格式化数字（添加千分位分隔符）
 * @param {number|string} number - 要格式化的数字
 * @param {number} decimals - 小数位数，默认为2
 * @param {string} separator - 千分位分隔符，默认为','
 * @returns {string} 格式化后的数字字符串
 * @example
 * formatNumber(1234567.89) // '1,234,567.89'
 * formatNumber(1234567.89, 0) // '1,234,568'
 * formatNumber(1234567.89, 1, ' ') // '1 234 567.9'
 */
export const formatNumber = (number, decimals = 2, separator = ',') => {
  if (number === null || number === undefined || number === '') return ''

  const num = parseFloat(number)
  if (isNaN(num)) return ''

  const fixed = num.toFixed(decimals)
  const parts = fixed.split('.')

  // 添加千分位分隔符
  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, separator)

  return parts.join('.')
}

/**
 * 格式化文件大小
 * @param {number} bytes - 字节数
 * @param {number} decimals - 小数位数，默认为2
 * @returns {string} 格式化后的文件大小
 * @example
 * formatFileSize(1024) // '1.00 KB'
 * formatFileSize(1048576) // '1.00 MB'
 * formatFileSize(1073741824, 1) // '1.0 GB'
 */
export const formatFileSize = (bytes, decimals = 2) => {
  if (bytes === 0) return '0 Bytes'
  if (!bytes || bytes < 0) return ''

  const k = 1024
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))

  return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + ' ' + sizes[i]
}

/**
 * 格式化百分比
 * @param {number} value - 数值（0-1之间或0-100之间）
 * @param {number} decimals - 小数位数，默认为2
 * @param {boolean} isDecimal - 输入值是否为小数形式（0-1），默认为true
 * @returns {string} 格式化后的百分比字符串
 * @example
 * formatPercentage(0.1234) // '12.34%'
 * formatPercentage(12.34, 2, false) // '12.34%'
 * formatPercentage(0.1234, 0) // '12%'
 */
export const formatPercentage = (value, decimals = 2, isDecimal = true) => {
  if (value === null || value === undefined || value === '') return ''

  const num = parseFloat(value)
  if (isNaN(num)) return ''

  const percentage = isDecimal ? num * 100 : num
  return percentage.toFixed(decimals) + '%'
}

/**
 * 格式化货币
 * @param {number|string} amount - 金额
 * @param {string} currency - 货币符号，默认为'¥'
 * @param {number} decimals - 小数位数，默认为2
 * @returns {string} 格式化后的货币字符串
 * @example
 * formatCurrency(1234.56) // '¥1,234.56'
 * formatCurrency(1234.56, '$') // '$1,234.56'
 * formatCurrency(1234.56, '¥', 0) // '¥1,235'
 */
export const formatCurrency = (amount, currency = '¥', decimals = 2) => {
  if (amount === null || amount === undefined || amount === '') return ''

  const num = parseFloat(amount)
  if (isNaN(num)) return ''

  return currency + formatNumber(num, decimals)
}

/**
 * 截断文本并添加省略号
 * @param {string} text - 要截断的文本
 * @param {number} maxLength - 最大长度
 * @param {string} suffix - 后缀，默认为'...'
 * @returns {string} 截断后的文本
 * @example
 * truncateText('这是一段很长的文本内容', 10) // '这是一段很长的文本...'
 * truncateText('短文本', 10) // '短文本'
 */
export const truncateText = (text, maxLength, suffix = '...') => {
  if (!text || typeof text !== 'string') return ''
  if (text.length <= maxLength) return text

  return text.substring(0, maxLength) + suffix
}

/**
 * 默认导出所有格式化函数
 */
export default {
  formatDate,
  getRelativeTime,
  formatTimestamp,
  getWeekday,
  formatDateRange,
  getTimePeriod,
  getDaysDiff,
  isToday,
  isYesterday,
  isTomorrow,
  getFriendlyDate,
  formatNumber,
  formatFileSize,
  formatPercentage,
  formatCurrency,
  truncateText
}